#### Modbus 通讯管理器，林恩德  2022.6.18
# 实现通信传输管理,使用独立的线程处理通讯事件
from __future__ import with_statement
import datetime
import logging
from logging.config import valid_ident
import struct
import modbus_tk
import modbus_tk.modbus_tcp as modbus_tcp
import modbus_tk.defines as mdef
import time
import threading
from core.state import MonitorType
from modbus.readfloat import WriteFloats,ReadFloat,WriteFloat
from core import LOGGER, getDataLogger,runningEvent

dataLogger = getDataLogger('datalogger','monitordata-200ms.log',200)

dataLogger1s = getDataLogger('datalogger1s','monitordata-1s.log',1*1000)

dataLogger10s = getDataLogger('datalogger10s','monitordata-10s.log',10*1000)


class ModbusManager(threading.Thread):
    def __init__(self,manager,port = 1252):  
        super().__init__(name="ModbusThread")    #args = manager)    
        self.manager = manager 
        self.running = False
        self.port = port
    def start(self):   

        LOGGER.info("ModbusTCP服务启动中...")
        self.server = modbus_tcp.TcpServer(self.port)
        self.server.start()
        self.running = True
        self.slave1 =  self.server.add_slave(1,unsigned=True)
            # add 2 blocks of holding registers
        self.slave1.add_block('monitor', mdef.HOLDING_REGISTERS, 0, 8000)  # address 0, length 100
        self.slave1.add_block('remotecontrol', mdef.COILS, 0, 100)
            # set the values of registers at address 0
        modbus_tk.hooks.install_hook('modbus.Slave.handle_write_single_coil_request', self.on_write_coil)
   
        super(ModbusManager,self).start()
    def on_write_coil(self,data):
        ###收到遥控数据
        slave, request_pdu = data
        (data_address, value) = struct.unpack(">HH", request_pdu[1:5])
        stateOn = value==0xff00
        if(data_address== 20):
            self.manager.control.charge(stateOn)
        elif(data_address== 21):
            self.manager.control.discharge(stateOn)
        LOGGER.info('收到遥控数据：{}:{}'.format(data_address,stateOn))
        #logger.info(bytes_data)
    ###更新遥测数据  ,存一份整数，存一份原始数据  
    def updateMonitorState(self,type,data):
        #data = self.slave1.get_values('monitor',100,10)
        #LOGGER.debug("Modbus Data:{}".format(data))
        #LOGGER.debug("Float Data:{}".format(ReadFloat(data[0:2],reverse=True)))
        #LOGGER.debug("Float Data:{}".format(WriteFloat(ReadFloat(data[0:2],reverse=True),True)))
        #LOGGER.debug("Float Data:{}".format(WriteFloats(data,True)))
        #self.slave1.set_values('monitor', 100,WriteFloats([7.756, -0.5, -5.0, 0.04, 73.2],True))
        if(type==MonitorType.BATTERY_STATE):
            self.slave1.set_values('monitor', 100,WriteFloats(data,True))
            #self.slave1.set_values('monitor', 200,WriteFloats(data))
            pass
        elif(type==MonitorType.CHARGE_STATE):
            self.slave1.set_values('monitor', 200, WriteFloats(data,True))
            #self.slave1.set_values('monitor', 210, WriteFloats(data))
            pass
        elif(type==MonitorType.DISCHARGE_STATE):
            self.slave1.set_values('monitor', 300,WriteFloats(data,True))
            #self.slave1.set_values('monitor', 220,WriteFloats(data))
            pass
    def run(self):
        LOGGER.info("ModbudTCP服务运行中")
        LOGGER.info("监测数据按200ms的频率存储在monitordata.log日志文件中")
        while(runningEvent.isSet()==False):
            values = self.slave1.get_values('monitor', 200, 30)
            dataLogger.info(str(values))
            dataLogger1s.info(str(values))
            dataLogger10s.info(str(values))
            ##LOGGER.info(values)
            time.sleep(0.2)
        LOGGER.info("ModbudTCP服务终止")
    ###此处仅仅是个例子，将负数转换为正数，将小数转换为整数，否则modbus传输失败
    def  formatData(self,tuple):
        result=[]
        for val in tuple:
            if(val<0): 
                val = -val
            result.append(int(val*10))
        return result   


if __name__ == "__main__":
   # manager = BatteryManager()
    modbus = ModbusManager({})
    modbus.start()
    #modbus.slave1.set_values('a', 0, 0)
    ##modbus.slave1.set_values('c', 0, 1)
    ##t = INA219Thread((slave1,))
    ###t.start()
    while runningEvent.isSet()==False:
        time.sleep(1)
        value = modbus.slave1.get_values('a', 1, 100)
        value40001 = int(value[0])
        print ('Registers[1-100]:', value)
        #value40001 +=1
        #slave1.set_values('a', 1, [value40001,2,3,4,5,6])    
        #slave1.set_values('a', 100, [value40001,2,3,4,5,6])   
